/* Copyright (c) 2016-2020 Enfry Ltd. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of Enfry. 
 * You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the agreements
 * you entered into with Enfry.
 */
package com.enfry.storage.interceptor;

import java.io.IOException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.enfry.storage.Response;
import com.enfry.storage.api.IApi;
import com.enfry.storage.api.IClient;
import com.enfry.storage.common.Constants;
import com.enfry.storage.common.StorageUtils;
import com.enfry.storage.entity.Api;
import com.enfry.storage.entity.Client;
import com.enfry.storage.exception.ExCode;

/**
 * 接口签名认证。
 * 
 * @Title com.enfry.storage.interceptor.TokenVerifyProcessor
 * @author liulei
 * @date 2016年7月25日
 */
public class TokenVerifyProcessor implements IProcessor {
	private static Logger logger = LoggerFactory
			.getLogger(TokenVerifyProcessor.class);
	// private boolean initialized;
	// private Map<String, Api> apiMap = new HashMap<String, Api>();

	@Resource
	private IApi apiService;
	@Resource
	private IClient clientService;

	@Override
	public boolean process(HttpServletRequest request,
			HttpServletResponse response, Object handler, String reqApiName)
			throws IOException {

		String appKey = request.getParameter("appKey");
		String token = request.getParameter("token");
		String ts = request.getParameter("ts");

		// 检查参数
		// ExCode exCode = checkParam(appKey, token, ts);
		// if(exCode != null) {
		// doReponse(response, exCode);
		// return false;
		// }

		// 检查客户端有效性
		Client client = clientService.getByAppKey(appKey);
		if (client == null) {
			doReponse(response, ExCode.CLIENT_INVALID);
			return false;
		}

		// 检查API有效性
		// Api api = apiMap.get(reqApiName);
		Api api = apiService.selectByName(reqApiName);
		if (api == null) {
			doReponse(response, ExCode.API_INVALID);
			return false;
		}
		if (api.isDisabled()) {
			doReponse(response, ExCode.API_DISABLED);
			return false;
		}

		// 检查授权
		ExCode exCode = checkToken(token, ts, client, api);
		if (exCode != null) {
			doReponse(response, exCode);
			return false;
		}

		return true;
	}

	private ExCode checkParam(String appKey, String token, String ts) {
		if (StringUtils.isEmpty(appKey) || StringUtils.isEmpty(token)
				|| StringUtils.isEmpty(ts)) {
			return ExCode.API_PARAM_LACK;
		}

		try {
			Long.parseLong(ts);
		} catch (Exception e) {
			return ExCode.API_PARAM_FORMAT;
		}

		return null;
	}

	private ExCode checkToken(String token, String ts, Client client, Api api)
			throws IOException {
		if ("img.api".equals(api.getApiName())) {
			if (Constants.GET_IMG_TS.toString().equals(ts)) {
				return null;
			} else {
				return ExCode.API_TOKEN_INVALID;
			}
		}
		long now = System.currentTimeMillis();
		long ts2 = Long.parseLong(ts);

		int expiredIn = api.getExpired();
		String secret = client.getSecret();
		String token2 = StorageUtils.sign(api.getApiName(), secret, ts2);
		if (!token2.equals(token)) {
			return ExCode.API_TOKEN_INVALID;
		}

		if (expiredIn != 0 && (now - ts2 > expiredIn * 1000 || now < ts2)) {
			return ExCode.API_TOKEN_EXPIRED;
		}
		return null;
	}

	private void doReponse(HttpServletResponse response, ExCode exCode)
			throws IOException {
		Response rep = new Response(exCode);
		String json = rep.toString();
		logger.debug(json);
		response.getWriter().write(json);
	}

}
